//! 集群配置模块
//! 
//! 提供集群节点的配置管理功能

use crate::cluster::traits::{ConfigManager};
use crate::cluster::{ClusterError, ClusterResult};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;
use std::time::Duration;
use uuid::Uuid;

/// 集群配置结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClusterConfig {
    /// 节点唯一标识符
    pub node_id: String,
    
    /// 绑定地址
    pub bind_addr: String,
    
    /// Redis客户端连接端口
    pub redis_port: u16,
    
    /// 集群内部通信端口 (通常是redis_port + 10000)
    pub cluster_port: u16,
    
    /// 种子节点列表 (用于初始集群发现)
    pub seeds: Vec<String>,
    
    /// 每个节点管理的槽数 (自动计算)
    pub slots_per_node: u16,
    
    /// 每个主节点的副本数
    pub replica_count: u8,
    
    /// 心跳间隔
    pub heartbeat_interval: Duration,
    
    /// 故障超时时间
    pub fail_timeout: Duration,
    
    /// 选举超时时间
    pub election_timeout: Duration,
    
    /// Gossip协议间隔
    pub gossip_interval: Duration,
    
    /// Gossip扇出数量
    pub gossip_fanout: u8,
    
    /// 数据迁移超时
    pub migration_timeout: Duration,
    
    /// 迁移批处理大小
    pub migration_batch_size: usize,
    
    /// 是否启用自动故障恢复
    pub auto_failover: bool,
    
    /// 副本是否只读
    pub replica_readonly: bool,
}

impl Default for ClusterConfig {
    fn default() -> Self {
        Self {
            node_id: Uuid::new_v4().to_string(),
            bind_addr: "0.0.0.0".to_string(),
            redis_port: 6379,
            cluster_port: 16379,
            seeds: vec![],
            slots_per_node: 5461, // 16384 / 3 默认3个节点
            replica_count: 1,
            heartbeat_interval: Duration::from_secs(1),
            fail_timeout: Duration::from_secs(5),
            election_timeout: Duration::from_secs(3),
            gossip_interval: Duration::from_millis(100),
            gossip_fanout: 3,
            migration_timeout: Duration::from_secs(60),
            migration_batch_size: 100,
            auto_failover: true,
            replica_readonly: true,
        }
    }
}

impl ClusterConfig {
    /// 创建新的集群配置
    pub fn new() -> Self {
        Self::default()
    }
    
    /// 设置节点ID
    pub fn with_node_id<S: Into<String>>(mut self, node_id: S) -> Self {
        self.node_id = node_id.into();
        self
    }
    
    /// 设置绑定地址
    pub fn with_bind_addr<S: Into<String>>(mut self, addr: S) -> Self {
        self.bind_addr = addr.into();
        self
    }
    
    /// 设置Redis端口
    pub fn with_redis_port(mut self, port: u16) -> Self {
        self.redis_port = port;
        // 自动设置集群端口
        self.cluster_port = port + 10000;
        self
    }
    
    /// 设置集群端口
    pub fn with_cluster_port(mut self, port: u16) -> Self {
        self.cluster_port = port;
        self
    }
    
    /// 添加种子节点
    pub fn add_seed<S: Into<String>>(mut self, seed: S) -> Self {
        self.seeds.push(seed.into());
        self
    }
    
    /// 设置种子节点列表
    pub fn with_seeds(mut self, seeds: Vec<String>) -> Self {
        self.seeds = seeds;
        self
    }
    
    /// 设置副本数量
    pub fn with_replica_count(mut self, count: u8) -> Self {
        self.replica_count = count;
        self
    }
    
    /// 启用或禁用自动故障恢复
    pub fn with_auto_failover(mut self, enabled: bool) -> Self {
        self.auto_failover = enabled;
        self
    }
    
    /// 获取Redis服务地址
    pub fn redis_addr(&self) -> String {
        format!("{}:{}", self.bind_addr, self.redis_port)
    }
    
    /// 获取集群服务地址
    pub fn cluster_addr(&self) -> String {
        format!("{}:{}", self.bind_addr, self.cluster_port)
    }
    
    /// 解析Redis地址为SocketAddr
    pub fn redis_socket_addr(&self) -> Result<SocketAddr, std::net::AddrParseError> {
        self.redis_addr().parse()
    }
    
    /// 解析集群地址为SocketAddr
    pub fn cluster_socket_addr(&self) -> Result<SocketAddr, std::net::AddrParseError> {
        self.cluster_addr().parse()
    }
    
    /// 从TOML文件加载配置
    pub fn from_toml_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self, Box<dyn std::error::Error>> {
        use crate::config::TomlConfigParser;
        use crate::config::ConfigLoader;
        
        let parser = TomlConfigParser;
        Ok(parser.load_from_file(path.as_ref())?)
    }
    
    /// 从配置文件加载（自动检测格式）
    pub fn from_config_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self, Box<dyn std::error::Error>> {
        use crate::config::load_config;
        
        Ok(load_config(path)?)
    }
    
    /// 保存配置到TOML文件
    pub fn save_to_toml_file<P: AsRef<std::path::Path>>(&self, path: P) -> Result<(), Box<dyn std::error::Error>> {
        let content = toml::to_string_pretty(self)?;
        std::fs::write(path, content)?;
        Ok(())
    }
    
    /// 验证配置有效性
    pub fn validate(&self) -> Result<(), String> {
        if self.node_id.is_empty() {
            return Err("节点ID不能为空".to_string());
        }
        
        if self.redis_port == 0 {
            return Err("Redis端口不能为0".to_string());
        }
        
        if self.cluster_port == 0 {
            return Err("集群端口不能为0".to_string());
        }
        
        if self.redis_port == self.cluster_port {
            return Err("Redis端口和集群端口不能相同".to_string());
        }
        
        if self.replica_count == 0 {
            return Err("副本数量至少为1".to_string());
        }
        
        if self.gossip_fanout == 0 {
            return Err("Gossip扇出数量至少为1".to_string());
        }
        
        Ok(())
    }
}

// =============================================================================
// Trait实现
// =============================================================================

#[async_trait]
impl ConfigManager for ClusterConfig {
    fn node_id(&self) -> &str {
        &self.node_id
    }
    
    fn bind_addr(&self) -> &str {
        &self.bind_addr
    }
    
    fn redis_port(&self) -> u16 {
        self.redis_port
    }
    
    fn cluster_port(&self) -> u16 {
        self.cluster_port
    }
    
    fn seeds(&self) -> &[String] {
        &self.seeds
    }
    
    fn validate(&self) -> Result<(), String> {
        self.validate()
    }
    
    fn redis_addr(&self) -> String {
        self.redis_addr()
    }
    
    fn cluster_addr(&self) -> String {
        self.cluster_addr()
    }
    
    async fn load_from_file<P: AsRef<std::path::Path> + Send>(&mut self, path: P) -> ClusterResult<()> {
        use crate::config::load_config;
        
        match load_config(path) {
            Ok(config) => {
                *self = config;
                Ok(())
            }
            Err(e) => Err(ClusterError::Config(format!("加载配置文件失败: {e}")))
        }
    }
    
    async fn save_to_file<P: AsRef<std::path::Path> + Send>(&self, path: P) -> ClusterResult<()> {
        self.save_to_toml_file(path)
            .map_err(|e| ClusterError::Config(format!("保存配置文件失败: {e}")))
    }
}

